package com.jd.user.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.jd.basic.exception.BusinessException;
import com.jd.basic.service.impl.BaseServiceImpl;
import com.jd.basic.util.AjaxResult;
import com.jd.user.domain.Logininfo;
import com.jd.user.domain.User;
import com.jd.user.mapper.LogininfoMapper;
import com.jd.user.mapper.UserMapper;
import com.jd.user.service.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.internet.MimeMessage;
import java.util.Map;

/**
 * 业务实现类：
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JavaMailSender javaMailSender;

    @Override
    @Transactional
    public void add(User user) { // 同步登录信息表
        // 对密码和盐值进行添加
        String salt = RandomUtil.randomString(32);
        String md5 = SecureUtil.md5(user.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5);
        // 新建一个登陆信息对象获取自增长id
        Logininfo logininfo = new Logininfo();
        // 用bean工具类复制，会将同名字段进行赋值
        BeanUtils.copyProperties(user, logininfo); // 此时user没有添加，logininfo id 为null
        logininfo.setType(1); // 设置type为用户
        logininfoMapper.add(logininfo); // 添加获取id
        user.setLogininfoId(logininfo.getId()); // 设置logininfoid
        super.add(user); // 添加user
    }

    @Override
    @Transactional
    public void update(User user) { // 修改同步logininfo
        // 获取旧的user信息
        User oldUser = userMapper.findOne(user.getId());
        // 密码盐值 loginId 不变
        user.setSalt(oldUser.getSalt());
        user.setPassword(oldUser.getPassword());
        user.setLogininfoId(oldUser.getLogininfoId());
        // 获取旧的logininfo信息
        Logininfo oldLogin = logininfoMapper.findOne(oldUser.getLogininfoId());
        BeanUtils.copyProperties(user, oldLogin);
        oldLogin.setId(oldUser.getLogininfoId());
        logininfoMapper.update(oldLogin);
        super.update(user);
    }

    @Override
    @Transactional
    public void del(Long id) {
        User user = userMapper.findOne(id);
        super.del(id);
        logininfoMapper.del(user.getLogininfoId());
    }

    @Override
    @Transactional
    public void patchDel(Long[] ids) {
        for (Long id : ids) {
            del(id);
        }
    }

    @Override
    public AjaxResult phoneRegister(Map<String, String> map) { // 手机注册业务
        //一：校验
        String phoneCode = map.get("phoneCode");
        String phone = map.get("phone");
        String password = map.get("password");
        String passwordRepeat = map.get("passwordRepeat");
        //1.空值校验
        if (StrUtil.isBlank(phoneCode) || StrUtil.isBlank(password) ||
                StrUtil.isBlank(passwordRepeat) || StrUtil.isBlank(phone)) {
            throw new BusinessException("信息不能为空！");
        }
        //2.手机短信验证码校验：a.是否过期 b.是否正确
        Object phoneCodeObj = redisTemplate.opsForValue().get("register:" + phone);
        if (phoneCodeObj == null) { // 过期
            throw new BusinessException("手机验证码已过期！");
        }
        // 没有过期，判断是否正确
        if (!phoneCodeObj.toString().split(":")[0].equals(phoneCode)) {
            throw new BusinessException("手机验证码错误！");
        }
        //3.密码一致性校验
        if (!passwordRepeat.equals(password)) {
            throw new BusinessException("两次密码不一致！");
        }
        //二：操作数据库
        //1.通过map的参数构建User对象【盐值和密码需要处理】
        User user = new User();
        String salt = RandomUtil.randomString(32);
        user.setUsername(phone);
        user.setSalt(salt);
        String md5 = SecureUtil.md5(password + salt);
        user.setPassword(md5);
        user.setPhone(phone);
        user.setState(1); // 启用
        //2.利用属性拷贝BeanUtils构建一个Logininfo对象
        Logininfo logininfo = new Logininfo(); // 获取id
        BeanUtils.copyProperties(user, logininfo);
        logininfo.setType(1); // 用户
        logininfo.setDisable(true); // 启用
        //3.先添加Logininfo对象 - 自增id
        logininfoMapper.add(logininfo);
        user.setLogininfoId(logininfo.getId());
        //4.将自增id设置到user对象再添加User对象到数据库
        userMapper.add(user);
        return new AjaxResult();
    }

    @Override
    public AjaxResult emailRegister(Map<String, String> map) { // 邮箱注册业务
        // 空值判断
        String email = map.get("email");
        String password = map.get("password");
        String passwordRepeat = map.get("passwordRepeat");
        if (StrUtil.isBlank(email) || StrUtil.isBlank(password) ||
                StrUtil.isBlank(passwordRepeat)) {
            throw new BusinessException("信息不能为空！");
        }
        // 密码一致性判断
        if (!password.equals(passwordRepeat)){
            throw new BusinessException("两次密码不一致！");
        }
        // 判断邮箱是否注册过
        User user = userMapper.findByEmail(email);
        if (user != null){ // 注册过
            throw new BusinessException("该邮箱已经注册过！");
        }
        User userObj = new User();
        // 对user密码盐值进行维护
        String salt = RandomUtil.randomString(32);
        userObj.setSalt(salt);
        String md5 = SecureUtil.md5(password + salt);
        userObj.setPassword(md5);
        // 设置用户名和邮箱,状态默认禁用，需要激活
        userObj.setUsername(email);
        userObj.setEmail(email);
        // 维护logininfo表
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(userObj,logininfo);
        logininfo.setType(1); // 用户
        logininfoMapper.add(logininfo);
        userObj.setLogininfoId(logininfo.getId());
        userMapper.add(userObj);
        // 给用户发送激活邮件
        try {
            //创建复杂邮件对象
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            //发送复杂邮件的工具类
            //true - 能够添加附件
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "utf-8");
            helper.setFrom("1178050280@qq.com"); // 发件人
            helper.setSubject("用户激活邮件");
            //true - 能够再内容中编写html标签 - 会解析
            helper.setText("<h1>你的账号已经注册成功!!!</h1>" +
                    "<a href='http://localhost/user/active/"+userObj.getId()+"'>点击该链接激活</a>", true);
            //添加附件
//            helper.addAttachment("p7.jpg", new File("C:\\Users\\Administrator\\Pictures\\photos\\p7.jpg"));
//            helper.addAttachment("g1.gif", new File("C:\\Users\\Administrator\\Pictures\\g1.gif"));
            //收件人
            helper.setTo(userObj.getEmail());
            javaMailSender.send(mimeMessage);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return new AjaxResult();
    }

    @Override
    public void emailActive(Long id) { // 邮件激活
        User user = userMapper.findOne(id);
        user.setState(1);
        userMapper.update(user);
        Logininfo logininfo = logininfoMapper.findOne(user.getLogininfoId());
        logininfo.setDisable(true);
        logininfoMapper.update(logininfo);
    }
}
